package service

import (
	sqlc "bgs/db/sqlc"
	"bgs/util"
	"context"

	"database/sql"
)

// EnsureStat 确保用户的统计信息并返回
func (s *UserServiceImp) EnsureStat(ctx context.Context, q *sqlc.Queries, withLock bool, userID int64) (userStat sqlc.UserStat, err error) {
	slog := util.NewContextLogger(ctx, s.slog)
	var sqlErr error
	if withLock {
		userStat, sqlErr = q.GetUserStatByUserIDToLock(ctx, userID)
	} else {
		userStat, sqlErr = q.GetUserStatByUserID(ctx, userID)
	}

	if sqlErr != nil {
		if sql.ErrNoRows == sqlErr {
			userStat, err = q.UpsertUserStat(ctx, sqlc.UpsertUserStatParams{
				UserID:               userID,
				FansCount:            0,
				FollowUserCount:      0,
				FollowBrandCount:     0,
				EndorseBrandCount:    0,
				EndorseActivityCount: 0,
				InvolveActivityCount: 0,
				OrderCount:           0,
				ViewCount:            0,
				PayAmount:            0,
			})
			if err != nil {
				return
			}
		} else {
			err = sqlErr
			return
		}
	}
	slog.Infof("确保用户的统计信息并返回 ok")
	return
}

// UpdateUserStatSinceBeFollowed 用户被关注后更新用户统计
func (s *UserServiceImp) UpdateUserStatSinceBeFollowed(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户被关注-确保获取锁定的用户统计记录(%d) ok", userID)

	newFansCount, err := q.CountUserFansByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[user_fans]统计用户的粉丝数 ok")

	err = q.UpdateUserStatSinceBeFollowed(ctx, sqlc.UpdateUserStatSinceBeFollowedParams{
		UserID:    userID,
		FansCount: int32(newFansCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户被关注后更新用户统计粉丝数(%d)->(%d) ok", userStatLocked.FansCount, newFansCount)
	return
}

// UpdateUserStatSinceFollowBrand 用户关注某个品牌后更新用户统计中的关注的品牌数
func (s *UserServiceImp) UpdateUserStatSinceFollowBrand(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户关注某个品牌-确保获取锁定的用户统计记录(%d) ok", userID)

	// newFollowBrandCount := userStatLocked.FollowBrandCount + 1

	newFollowBrandCount, err := q.CountBrandFollowsByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[brand_follows]统计关注的品牌数 ok")

	err = q.UpdateUserStatSinceFollowBrand(ctx, sqlc.UpdateUserStatSinceFollowBrandParams{
		UserID:           userID,
		FollowBrandCount: int32(newFollowBrandCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户关注某个品牌后更新用户统计中的关注品牌数(%d)->(%d) ok", userStatLocked.FollowBrandCount, newFollowBrandCount)
	return
}

// UpdateUserStatSinceFollowStore 用户关注某个门店后更新用户统计中的关注的门店数
func (s *UserServiceImp) UpdateUserStatSinceFollowStore(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户关注某个门店-确保获取锁定的用户统计记录(%d) ok", userID)

	newFollowStoreCount, err := q.CountStoreFollowsByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[store_follows]统计关注的门店数 ok")

	err = q.UpdateUserStatSinceFollowStore(ctx, sqlc.UpdateUserStatSinceFollowStoreParams{
		UserID:           userID,
		FollowStoreCount: int32(newFollowStoreCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户关注某个门店后更新用户统计中的关注门店数(%d)->(%d) ok", userStatLocked.FollowStoreCount, newFollowStoreCount)
	return
}

// UpdateUserStatSinceFollowUser 用户关注某个用户后更新用户统计中的关注的用户数
func (s *UserServiceImp) UpdateUserStatSinceFollowUser(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户关注某个用户-确保获取锁定的用户统计记录(%d) ok", userID)

	// newFollowUserCount := userStatLocked.FollowUserCount + 1

	newFollowUserCount, err := q.CountUserFollowsByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[user_follows]统计关注的用户数 ok")

	err = q.UpdateUserStatSinceFollowUser(ctx, sqlc.UpdateUserStatSinceFollowUserParams{
		UserID:          userID,
		FollowUserCount: int32(newFollowUserCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户关注某个用户后更新用户统计中的关注的用户数(%d)->(%d) ok", userStatLocked.FollowUserCount, newFollowUserCount)
	return
}

// UpdateUserStatSinceBecomeSpokesman 用户成为某品牌代言人后更新用户统计代言品牌数
func (s *UserServiceImp) UpdateUserStatSinceBecomeBrandSpokesman(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户成为某品牌代言人-确保获取锁定的用户统计记录(%d) ok", userID)

	// newEndorseBrandCount := userStatLocked.EndorseBrandCount + 1

	newEndorseBrandCount, err := q.CountNormalBrandSpokesmansByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[spokesmans]统计代言品牌数 ok")

	err = q.UpdateUserStatSinceBecomeBrandSpokesman(ctx, sqlc.UpdateUserStatSinceBecomeBrandSpokesmanParams{
		UserID:            userID,
		EndorseBrandCount: int32(newEndorseBrandCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户成为某品牌代言人后更新用户统计代言品牌数(%d)->(%d) ok", userStatLocked.EndorseBrandCount, newEndorseBrandCount)
	return
}

// UpdateUserStatSinceBecomeStoreSpokesman 用户成为某门店代言人后更新用户统计代言门店数
func (s *UserServiceImp) UpdateUserStatSinceBecomeStoreSpokesman(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户成为某品牌代言人-确保获取锁定的用户统计记录(%d) ok", userID)

	newEndorseStoreCount, err := q.CountNormalStoreSpokesmansByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[spokesmans]统计代言门店数 ok")

	err = q.UpdateUserStatSinceBecomeStoreSpokesman(ctx, sqlc.UpdateUserStatSinceBecomeStoreSpokesmanParams{
		UserID:            userID,
		EndorseStoreCount: int32(newEndorseStoreCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户成为某门店代言人后更新用户统计代言门店数(%d)->(%d) ok", userStatLocked.EndorseStoreCount, newEndorseStoreCount)
	return
}

// UpdateUserStatSinceActivityEndorsed 用户代言品牌活动后更新用户统计代言活动数
func (s *UserServiceImp) UpdateUserStatSinceActivityEndorsed(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、用户代言品牌活动-确保获取锁定的用户统计记录(%d) ok", userID)

	// newEndorseActivityCount := userStatLocked.EndorseActivityCount + 1
	newEndorseActivityCount, err := q.CountSpokesmanOwnActivitiesByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、从[activities]统计代言活动数 ok")

	err = q.UpdateUserStatSinceActivityEndorsed(ctx, sqlc.UpdateUserStatSinceActivityEndorsedParams{
		UserID:               userID,
		EndorseActivityCount: int32(newEndorseActivityCount),
	})
	if err != nil {
		return
	}

	slog.Infof("3、用户代言品牌活动后更新用户统计代言活动数(%d)->(%d) ok", userStatLocked.EndorseActivityCount, newEndorseActivityCount)
	return
}

// UpdateStatSinceOrderCreated 新订单下单更新用户统计
func (s *UserServiceImp) UpdateStatSinceOrderCreated(ctx context.Context, q *sqlc.Queries, orderPtr *sqlc.Order) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userID := orderPtr.UserID
	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、订单创建-确保获取锁定的用户统计记录(%d) ok", userID)

	newOrderCount, err := q.CountOrdersByUserID(ctx, userID)
	if err != nil {
		return
	}
	slog.Infof("2、统计当前订单创建后当前用户的订单数量 ok")

	var newInvolveActivityCount int32
	if orderPtr.OrderType == string(sqlc.EmActivityTypeGroupBuying1) {
		// 交易类,下单算参与活动
		newInvolveActivityCount, err = s.aggrInvolveActivityCount(ctx, q, userID)
		if err != nil {
			return
		}
		slog.Infof("3、交易类活动下单算参与活动, 统计当前订单创建后当前用户对于该活动的订单数量 ok")
	} else {
		// 非交易类下单不算
		newInvolveActivityCount = userStatLocked.InvolveActivityCount
		slog.Infof("3、非交易类活动下单不算参与活动, 略过 ok")
	}

	// newInvolveActivityCount, err = q.AggrActivityCountOfOrderingByUserID(ctx, userID)

	// rawInvolveActivityCount := userStatLocked.InvolveActivityCount

	// // newInvolveActivityCount := rawInvolveActivityCount + util.Int32IfThenElse(orderCountOfActivity == 1, 1, 0) // 包含当前这个订单,订单用户在活动下的统计数==1表示是对该活动下的第一单需要jia1
	// newOrderCount := orderCount

	err = q.UpdateUserStatSinceOrderCreated(ctx, sqlc.UpdateUserStatSinceOrderCreatedParams{
		UserID:               userID,
		InvolveActivityCount: newInvolveActivityCount,
		OrderCount:           int32(newOrderCount),
	})
	if err != nil {
		return
	}

	slog.Infof("4、新订单下单更新用户统计正向下单部分字段raw{InvolveActivityCount:%d, OrderCount:%d}=>new{InvolveActivityCount:%d, OrderCount:%d} ok",
		userStatLocked.InvolveActivityCount, userStatLocked.OrderCount, newInvolveActivityCount, newOrderCount)
	return
}

// UpdateUserStatSinceOrderPayed 新订单支付成功更新用户统计
func (s *UserServiceImp) UpdateStatSinceOrderPayed(ctx context.Context, q *sqlc.Queries, orderPtr *sqlc.Order) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	activityID := orderPtr.ActivityID
	userID := orderPtr.UserID
	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("1、订单支付成功-确保获取锁定的用户统计记录(%d) ok", userID)

	payAmount, err := q.AggrOrderPayAmountByActivityIDAndUserID(ctx, sqlc.AggrOrderPayAmountByActivityIDAndUserIDParams{
		ActivityID: activityID,
		UserID:     userID,
	})
	if err != nil {
		return
	}
	slog.Infof("2、统计当前订单支付成功后当前用户对于该活动的付款金额 ok")

	rawPayAmount := userStatLocked.PayAmount
	slog.Infof("1、rawPayAmount(%d), newPayAmount(%d) ok", rawPayAmount, payAmount)

	err = q.UpdateUserStatSinceOrderPayed(ctx, sqlc.UpdateUserStatSinceOrderPayedParams{
		UserID:    userID,
		PayAmount: payAmount,
	})
	if err != nil {
		return
	}

	slog.Infof("3、新订单支付成功更新用户统计正向下单部分字段 ok")
	return
}

// UpdateStatSinceFirstActivityUserInteracted 首次活动交互更新用户统计
func (s *UserServiceImp) UpdateStatSinceFirstActivityUserInteracted(ctx context.Context, q *sqlc.Queries, userID int64) (err error) {
	slog := util.NewContextLogger(ctx, s.slog)

	userStatLocked, err := s.EnsureStat(ctx, q, true, userID)
	if err != nil {
		return
	}
	slog.Infof("首次活动交互-确保获取锁定的用户统计记录(%d) ok", userID)

	newInvolveActivityCount, err := s.aggrInvolveActivityCount(ctx, q, userID)
	if err != nil {
		return
	}
	slog.Infof("2、交易类活动下单算参与活动, 统计当前订单创建后当前用户对于该活动的订单数量 ok")

	err = q.UpdateUserStatSinceActivityUserProcedureCreated(ctx, sqlc.UpdateUserStatSinceActivityUserProcedureCreatedParams{
		UserID:               userID,
		InvolveActivityCount: newInvolveActivityCount,
	})
	if err != nil {
		return
	}

	slog.Infof("4、首次活动交互更新用户统计 部分字段raw{InvolveActivityCount:%d}=>new{InvolveActivityCount:%d} ok",
		userStatLocked.InvolveActivityCount, newInvolveActivityCount)
	return
}

// aggrInvolveActivityCount 统计用户参与的活动数(交易类例如团购按照下单维度,非交易类按照用户活动过程记录来统计)
func (s *UserServiceImp) aggrInvolveActivityCount(ctx context.Context, q *sqlc.Queries, userID int64) (involveActivityCount int32, err error) {
	aggrInvolveActivityCountOfOrdering, err := q.AggrActivityCountOfOrderingByUserID(ctx, userID)
	if err != nil {
		return
	}

	aggrInvolveActivityCountOfUserProcedure, err := q.AggrActivityCountOfUserProcedureByUserID(ctx, userID)
	if err != nil {
		return
	}

	involveActivityCount = int32(aggrInvolveActivityCountOfOrdering + aggrInvolveActivityCountOfUserProcedure)
	return
}
